package net.sf.midollo.io.buffer;

import net.sf.midollo.lock.SupplierConsumerLock;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;

public class InputStreamBuffer implements Runnable {

	protected final SupplierConsumerLock lock = new SupplierConsumerLock();
	protected final InputStream is;
	protected final byte[] buffer;
	protected boolean eof;
	protected int count;
	protected IOException error;

	public InputStreamBuffer(InputStream is, byte[] buffer) {
		this.is = is;
		this.buffer = buffer;
		this.eof = false;
		this.count = 0;
		this.error = null;
	}

	public boolean isEof() {
		return this.eof;
	}

	public int getCount() {
		return this.count;
	}

	public IOException getError() {
		return this.error;
	}

	public boolean lock(long timeout) throws InterruptedException {
		return this.lock.readLock(timeout);
	}

	public void unlock() {
		this.lock.readUnlock();
	}

	public void run() {
		int len;
		int nread;
		do {
			try {
				this.lock.writeLock();
				len = this.buffer.length;
				this.count = 0;
				do {
					nread = this.is.read(this.buffer, this.count, len);
					if (nread < 0) {
						this.eof = true;
						return;
					}
					this.count += nread;
					len -= nread;
					if (len <= 0)
						break;
					if (this.is.available() <= 0)
						break;
				} while (true);
			} catch (InterruptedException e) {
				this.error = new InterruptedIOException(e.toString());
				return;
			} catch (IOException e) {
				this.error = e;
				return;
			} finally {
				this.lock.writeUnlock();
			}
		} while (true);
	}
}
